/*
@title: dexter_nightshift
@description: Dexter must grab the knife and kill the victim before Doakes catches him! Includes hazards and multiple maps. 
@author: Kings-Indian
@tags: ['stealth', 'puzzle', 'multiplayer']
@addedOn: 2025-08-19
Instructions:
Player 1 (Dexter): Use WASD to move. Grab the knife (k) and then reach the victim (t).
Player 2 (Doakes): Use IJKL to move. Catch Dexter (d) before he kills the victim.
Walls (w) block movement. Hazards (h) instantly kill Dexter if he steps on them.
If Dexter wins a map, the game automatically advances to the next one.
*/
const dexter = "d";
const target = "t";
const doakes = "c";
const knife = "k";
const wall = "w";
const hazard = "h";
// Sprites
setLegend(
  [ dexter, bitmap`
................
................
......000000....
......003003....
...0..000000....
...00.003003....
...00.003003....
...00.003333....
...00..0........
..0000.0........
...00..0........
...00000000.....
.......0........
......000.......
......0.0.......
......0.0.......` ],
  [ target, bitmap`
................
................
................
................
................
....000000......
....033330......
..00000000......
....606066......
....606066......
....66660.......
........0.......
.....0000.......
.....0000.......
.....0000.......
.......00.......` ],
  [ doakes, bitmap`
................
................
................
................
................
......5555......
......5555......
......CCCC......
......0660......
......6336......
.......66.......
.....655556.....
.....6.55.6.....
.....6.55.6.....
.......55.......
.......55.......` ],
  [ knife, bitmap`
.......33.......
......3333......
.....333233.....
.....033223.....
.....023023.....
.....020020.....
.....020220.....
.....020020.....
.....022020.....
.....020020.....
....00000000....
...0000000000...
.......CC.......
.......CC.......
.......CC.......
.......96.......` ],
  [ wall, bitmap`
0000000000000000
0000000000000000
0000L00000000000
0000L00000000000
00000000000L0000
0000000000000000
000000000000L000
00000L0000000000
0000000LL0000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
000LL00000L00000
0000000000000000
0000000000000000` ],
  [ hazard, bitmap`
................
................
................
................
......6666......
.....688886.....
.....688886.....
......6666......
......6666......
.....688886.....
.....688886.....
......6666......
................
................
................
................` ]
);
// Levels
const levels = [
  map`
wwwwwwwwwwwwwwww
wd.....k.......w
w..wwwwwww.....w
w..............w
w.....c........w
w..........t...w
w..............w
wwwwwwwwwwwwwwww`,
  map`
wwwwwwwwwwwwwwww
wd....w...k....w
w.w..h.w.......w
w.w............w
w....c....h....w
w....h......t..w
w..............w
wwwwwwwwwwwwwwww`,
  map`
wwwwwwwwwwwwwwww
w..d...........w
w....wwwwwww...w
w..k....h......w
w..............w
w.....c........w
w..........t...w
wwwwwwwwwwwwwwww`
];
let level = 0;
setMap(levels[level]);
// Solids
setSolids([ wall ]);
// State
let dexterHasKnife = false;
let gameOver = false;
// Dexter’s movement (WASD)
onInput("w", () => moveCharacter(dexter, 0, -1));
onInput("s", () => moveCharacter(dexter, 0, 1));
onInput("a", () => moveCharacter(dexter, -1, 0));
onInput("d", () => moveCharacter(dexter, 1, 0));
// Doakes’ movement (IJKL)
onInput("i", () => moveCharacter(doakes, 0, -1));
onInput("k", () => moveCharacter(doakes, 0, 1));
onInput("j", () => moveCharacter(doakes, -1, 0));
onInput("l", () => moveCharacter(doakes, 1, 0));
// Movement helper
function moveCharacter(type, dx, dy) {
  if (gameOver) return;
  const sprite = getFirst(type);
  const nextX = sprite.x + dx;
  const nextY = sprite.y + dy;
  if (!tileHasType(nextX, nextY, wall)) {
    sprite.x = nextX;
    sprite.y = nextY;
  }
}
// Check tile contents
const tileHasType = (x, y, type) => getTile(x, y).some(s => s.type === type);
// Full screen message
function fullScreenMessage(text, colorCode) {
  clearText();
  for (let y = 0; y < 8; y++) {
    addText(text, { y, color: colorCode });
  }
}
// Load next level or end
function nextLevel() {
  level++;
  if (level < levels.length) {
    setMap(levels[level]);
    dexterHasKnife = false;
    gameOver = false;
    clearText();
  } else {
    fullScreenMessage("GAME COMPLETE!", color`9`);
    gameOver = true;
  }
}
// After each move
afterInput(() => {
  if (gameOver) return;
  const d = getFirst(dexter);
  const c = getFirst(doakes);
  if (!d || !c) return;
  // Dexter interactions
  const tile = getTile(d.x, d.y);
  tile.forEach(obj => {
    if (obj.type === knife) {
      obj.remove();
      dexterHasKnife = true;
      addText("Dexter armed!", { y: 0, color: color`3` });
    }
    if (obj.type === target) {
      if (dexterHasKnife) {
        obj.remove();
        fullScreenMessage("DEXTER WINS!", color`9`);
        gameOver = true;
        setTimeout(nextLevel, 1000);
      } else {
        addText("Need a weapon!", { y: 1, color: color`6` });
      }
    }
    if (obj.type === hazard) {
      fullScreenMessage("DEXTER DIED!", color`6`);
      gameOver = true;
    }
  });
  // Doakes catches Dexter
  if (d.x === c.x && d.y === c.y) {
    fullScreenMessage("DOAKES WINS!", color`2`);
    gameOver = true;
  }
});
